//==================================================================================================
/**
  EVE - Expressive Vector Engine
  Copyright : EVE Project Contributors
  SPDX-License-Identifier: BSL-1.0
**/
//==================================================================================================
#include "test.hpp"

#include <eve/module/core.hpp>

#include <cmath>

//==================================================================================================
// Types tests
//==================================================================================================
TTS_CASE_TPL("Check return types of oneosqrteps", eve::test::simd::ieee_reals_wf16)
<typename T>(tts::type<T>)
{
  using v_t = eve::element_type_t<T>;
  using eve::as;

  TTS_EXPR_IS(eve::oneosqrteps(as<T>()), T);
  TTS_EXPR_IS(eve::oneosqrteps(as<v_t>()), v_t);
};

//==================================================================================================
// oneosqrteps  tests
//==================================================================================================
TTS_CASE_TPL("Check behavior of oneosqrteps on wide", eve::test::simd::ieee_reals_wf16)
<typename T>(tts::type<T>)
{
  using eve::as;
  using eve::lower;
  using eve::upper;
  using elt_t = eve::element_type_t<T>;

  TTS_EQUAL(eve::oneosqrteps(as<T>()), T(1.0l / eve::sqrt(eve::eps(as<eve::element_type_t<T>>()))));
  if constexpr(sizeof(elt_t) == 8)
  {
    TTS_EXPECT(eve::all(eve::oneosqrteps[lower](as<elt_t>())
                        <= std::sqrt(1.0l / (long double)(eve::eps(as<elt_t>())))));
    TTS_EXPECT(eve::all(eve::oneosqrteps[upper](as<elt_t>())
                      >= std::sqrt(1.0l / (long double)(eve::eps(as<elt_t>())))));
  }
  else
  {
    TTS_EXPECT(eve::all(eve::oneosqrteps[lower](as<elt_t>())
                        <= std::sqrt(1.0 / (double)(eve::eps(as<elt_t>())))));
    TTS_EXPECT(eve::all(eve::oneosqrteps[upper](as<elt_t>())
                        >= std::sqrt(1.0 / (double)(eve::eps(as<elt_t>())))));
  }
  TTS_EXPECT(eve::all(eve::oneosqrteps[lower](as<T>()) <= eve::oneosqrteps(as<T>())));
  TTS_EXPECT(eve::all(eve::oneosqrteps(as<T>()) <= eve::oneosqrteps[upper](as<T>())));
  TTS_ULP_EQUAL(eve::oneosqrteps[lower](as<T>()), eve::oneosqrteps[upper](as<T>()), 0.5);
};
